#include "ReferenceCountingInterface.h"
#include "Locking.h"

//template <typename T>
//class RefCountingTraits
//{
//public:
//	static void Refer(T* p)
//	{
//		p->IncRef();
//	}
//	static void Unrefer(T* p)
//	{
//		p->DecRef();
//	}
//};
template <typename HierarchyId>
class RefCountingTraits
{
};

template <typename T, typename HierarchyTraits = RefCountingTraits<T::HierarchyId> >
class Traits : public HierarchyTraits
{
};

//*Specialize whole hierarchy
template <>
class RefCountingTraits<Shape::HierarchyId>
{
public:
	static void Refer(Shape* p)
	{
		p->IncRef();
	}
	static void Unrefer(Shape* p)
	{
		cout << "Specialized RefCountingTraits<Shape::HierarchyId>" << endl;
		p->DecRef();
	}
};

//*Specialized single class
template <>
class Traits<Ellipse>
{
public:
	static void Refer(Shape* p)
	{
		p->IncRef();
	}
	static void Unrefer(Shape* p)
	{
		cout << "Specialized Traits<Ellipse>" << endl;
		p->DecRef();
	}
};

//*Specialize
template <>
class RefCountingTraits<Widget::HierarchyId>
{
public:
	static void Refer(Widget* p)
	{
		p->AddReference();
	}
	static void Unrefer(Widget* p)
	{
		cout << "Specialized RefCountingTraits<Widget::HierarchyId>" << endl;
		if(p->RemoveReference() == 0)
			delete p;
	}
};

class MtRefCountingTraits
{
public:
	void Refer(Widget* p)
	{
		Sentry s(lock_);
		p->AddReference();
	}
	void Unrefer(Widget* p)
	{
		Sentry s(lock_);
		cout << "Specialized MtRefCountingTraits" << endl;
		if(p->RemoveReference() == 0)
			delete p;
	}
private:
	Lock lock_;
};